package com.project.demo.service;

import com.project.demo.config.CosConfig;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * 腾讯云COS服务类
 */
@Slf4j
@Service
public class CosService {
    
    @Autowired
    private CosConfig cosConfig;
    
    private COSClient cosClient;
    
    /**
     * 获取COS客户端
     */
    private COSClient getCosClient() {
        if (cosClient == null) {
            COSCredentials cred = new BasicCOSCredentials(cosConfig.getSecretId(), cosConfig.getSecretKey());
            Region region = new Region(cosConfig.getRegion());
            ClientConfig clientConfig = new ClientConfig(region);
            cosClient = new COSClient(cred, clientConfig);
        }
        return cosClient;
    }
    
    /**
     * 上传文件到COS
     * @param file 文件
     * @return 文件访问URL
     */
    public String uploadFile(MultipartFile file) {
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        
        InputStream inputStream = null;
        try {
            // 获取原始文件名
            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || originalFilename.isEmpty()) {
                originalFilename = "file";
            }
            
            // 生成文件路径
            String filePath = generateFilePath(originalFilename);
            
            // 获取文件输入流
            inputStream = file.getInputStream();
            
            // 设置文件元数据
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentLength(file.getSize());
            String contentType = file.getContentType();
            if (contentType != null && !contentType.isEmpty()) {
                metadata.setContentType(contentType);
            }
            
            // 创建上传请求
            PutObjectRequest putObjectRequest = new PutObjectRequest(
                cosConfig.getBucket(),
                filePath,
                inputStream,
                metadata
            );
            
            // 执行上传
            COSClient client = getCosClient();
            client.putObject(putObjectRequest);
            
            // 生成文件访问URL
            String fileUrl = cosConfig.getHost() + "/" + filePath;
            
            log.info("文件上传成功: {} -> {}", originalFilename, fileUrl);
            return fileUrl;
            
        } catch (CosServiceException e) {
            log.error("COS服务异常: ErrorCode={}, ErrorMessage={}, RequestId={}", 
                e.getErrorCode(), e.getErrorMessage(), e.getRequestId());
            throw new RuntimeException("文件上传失败: " + e.getErrorMessage());
        } catch (CosClientException e) {
            log.error("COS客户端异常: {}", e.getMessage(), e);
            throw new RuntimeException("文件上传失败: " + e.getMessage());
        } catch (IOException e) {
            log.error("文件读取异常: {}", e.getMessage(), e);
            throw new RuntimeException("文件读取失败: " + e.getMessage());
        } finally {
            // 关闭输入流
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.warn("关闭输入流失败: {}", e.getMessage());
                }
            }
        }
    }
    
    /**
     * 生成文件路径
     * @param originalFilename 原始文件名
     * @return 文件路径
     */
    private String generateFilePath(String originalFilename) {
        // 获取文件扩展名
        String extension = "";
        int lastDotIndex = originalFilename.lastIndexOf(".");
        if (lastDotIndex > 0) {
            extension = originalFilename.substring(lastDotIndex);
        }
        
        // 生成日期路径
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String datePath = sdf.format(new Date());
        
        // 生成唯一文件名
        String fileName = UUID.randomUUID().toString().replace("-", "") + extension;
        
        // 组合完整路径
        return cosConfig.getPathPrefix() + datePath + "/" + fileName;
    }
    
    /**
     * 删除文件
     * @param fileUrl 文件URL
     * @return 是否删除成功
     */
    public boolean deleteFile(String fileUrl) {
        try {
            // 从URL中提取文件路径
            String filePath = extractFilePathFromUrl(fileUrl);
            
            if (filePath == null || filePath.isEmpty()) {
                log.warn("无法从URL中提取文件路径: {}", fileUrl);
                return false;
            }
            
            // 删除文件
            COSClient client = getCosClient();
            client.deleteObject(cosConfig.getBucket(), filePath);
            
            log.info("文件删除成功: {}", filePath);
            return true;
            
        } catch (CosServiceException e) {
            log.error("COS服务异常: {}", e.getMessage(), e);
            return false;
        } catch (CosClientException e) {
            log.error("COS客户端异常: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 从URL中提取文件路径
     * @param fileUrl 文件URL
     * @return 文件路径
     */
    private String extractFilePathFromUrl(String fileUrl) {
        if (fileUrl == null || fileUrl.isEmpty()) {
            return null;
        }
        
        // 移除域名部分
        String host = cosConfig.getHost();
        if (fileUrl.startsWith(host)) {
            return fileUrl.substring(host.length() + 1); // +1 是移除开头的 "/"
        }
        
        // 如果URL以 /api/upload/ 开头，移除该前缀
        if (fileUrl.startsWith("/api/upload/")) {
            return cosConfig.getPathPrefix() + fileUrl.substring("/api/upload/".length());
        }
        
        // 如果URL以 /upload/ 开头，移除该前缀
        if (fileUrl.startsWith("/upload/")) {
            return cosConfig.getPathPrefix() + fileUrl.substring("/upload/".length());
        }
        
        return fileUrl;
    }
}

